package labox.innovation.db;

import java.nio.Buffer;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javolution.util.FastList;
import labox.innovation.config.Config;
import labox.innovation.db.core.HeapByteBuffer;
import labox.innovation.db.core.SqlData;
import labox.innovation.db.manager.DBConnetionStateManager;
import labox.innovation.db.proxy.ConnectionProxy;
import labox.innovation.db.proxy.PreparedStatementProxy;
import labox.innovation.db.util.DbUtil;
import labox.innovation.db.util.SqlDataIdFactory;
import labox.innovation.gameserver.datatables.ClanTable;
import labox.innovation.gameserver.datatables.PlayerTemplateTable;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.L2ShortCut;
import labox.innovation.gameserver.model.actor.appearance.PcAppearance;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.base.ClassId;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PlayerDb {
	private static Logger _log = LoggerFactory.getLogger(PlayerDb.class.getName());

	/**
	 * ����һ����ɫ
	 */
	private static final String SAVE_CHARACTERS = "insert into characters (account_name,charId,char_name,sex,classid,accesslevel,createTime,online) values(?,?,?,?,?,?,?,?)";

	/**
	 * ����һ����ɫ
	 */
	private static final String UPDATE_CHARACTER = "update characters set lastAccess=?,level=?,person_signature=?,scene=?,details=?,onlinetime=?,online=?,appearance=?,paperdoll=?,isLoginTip=?,province=?,city=?,chatSwitches=?,accesslevel=? where charId=?";

	/**
	 * ���ؽ�ɫ
	 */
	private static final String LOAD_CHARACTER = "select account_name,char_name,sex,classid,level,scene,paperdoll,onlinetime,person_signature,details,appearance,paperdoll,isLoginTip,province,city,chatSwitches,accesslevel from characters where charId=?";

	/**
	 * �����˻��µ����н�ɫ
	 */
	private static final String SELECT_ACCOUNT_CHARACTERS = "select charId,char_name,level,clanid,classid,scene,deletetime,appearance,paperdoll from characters where account_name=?";

	/**
	 * ���½�ɫ����״̬
	 */
	private static final String UPDATE_ONLINE_STATUS = "UPDATE characters SET online=?, lastAccess=? WHERE charId=?";

	/**
	 * ��ϸ��ɫɾ��ʱ��
	 */
	private static final String UPDATE_CHARACTER_DELETE_TIME = "UPDATE characters SET deletetime=? WHERE charId=?";

	/**
	 * ���ý�ɫ���Ƿ����
	 */
	private static final String CHECK_CHARACTER_NAME_EXSIST = "SELECT account_name FROM characters WHERE char_name=?";

	/**
	 * ��ѯ�˻��µĽ�ɫ����
	 */
	private static final String SELECT_ACCOUNT_CHARACTERS_COUNT = "SELECT COUNT(char_name) FROM characters WHERE account_name=?";

	/**
	 * �����˻��µ����н�ɫ��ID,�����
	 */
	private static final String LOADALLCHARACTERS = "SELECT charId,char_name FROM characters";

	/**
	 * ��ݽ�ɫ��Ʋ�ѯ��ɫID
	 */
	private static final String SELECT_CHARACTERID_BY_NAME = "SELECT charId FROM characters WHERE char_name=?";

	/**
	 * ��ݽ�ɫID��ѯ��ɫ���
	 */
	private static final String SELECT_CHARACTERNAME_BY_ID = "SELECT char_name FROM characters WHERE charId=?";

	/**
	 * ��ݽ�ɫID��ѯ����ID
	 */
	private static final String SELECT_CLANID_BY_CHARACTERID = "SELECT clanId from characters WHERE charId=?";

	/**
	 * ɾ���ɫ
	 */
	public static final String PHYSICAL_DELETE_CHAR_BY_ID = "delete from characters where charId=?";

	/**
	 * ����һ����ɫ
	 * 
	 * @param player
	 * @return ����ɹ�Ϊtrue,����Ϊfalse
	 * @throws SQLException
	 */
	public static boolean createplayer(FuzePcInstance player) throws SQLException {
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		try {
			if (!DBConnetionStateManager.getDbState())
				return false;
			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(SAVE_CHARACTERS);
			if (DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt)) {
				ptmt.setString(1, player.getAccountName());
				ptmt.setLong(2, player.getObjectId());
				ptmt.setString(3, player.getName());
				ptmt.setInt(4, player.getAppearance().getSex().getId());
				ptmt.setInt(5, player.getClassId().getId());
				ptmt.setInt(6, player.getAccessLevel().getLevel());
				ptmt.setLong(7, System.currentTimeMillis());
				ptmt.setInt(8, player.isOnline());
				return ptmt.executeUpdate() > 0 ? true : false;
			} else
				return false;
		} finally {
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}

	}

	/***
	 * ���½�ɫ
	 * 
	 * @param player
	 * @return
	 */
	/**
	 * @param player
	 * @return
	 * @throws SQLException
	 */
	public static boolean storeplayer(FuzePcInstance player) throws SQLException {
		HeapByteBuffer _buf = HeapByteBuffer.newInstance();
		_buf.clear();
		// �����д��HeapByteBuffer
		_buf.writeInt(player.getCurrentHp()); // 1
		_buf.writeInt(player.getCurrentMp());// 2
		_buf.writeInt(player.getExp());// 3
		_buf.writeShort(player.getKarma());// 4
		_buf.writeLong(player.getClanId());// 5
		_buf.writeByte(player.getPracticeId().getId());// 6
		_buf.writeShort(player.getX());// 7
		_buf.writeShort(player.getY());// 8
		_buf.writeInt(player.getStat().getAssignedSTR());// 9
		_buf.writeInt(player.getStat().getAssignedDEX());// 10
		_buf.writeInt(player.getStat().getAssignedINT());// 11
		_buf.writeInt(player.getStat().getAssignedMEN());// 12
		_buf.writeInt(player.getStat().getAssignedCON());// 13
		_buf.writeInt(player.getStat().getUnassignedPoint());// 14
		_buf.writeByte(player.getAllShortCuts().size());// 15
		for (L2ShortCut sc : player.getAllShortCuts()) {
			_buf.writeByte(sc.getSlot());// 16
			_buf.writeByte(sc.getType());// 17
			_buf.writeLong(sc.getId());// 18
		}
		_buf.writeInt(player.getStat().getAutoAddLevel() ? 1 : 0);// 19
		_buf.writeInt(player.getPunish().getPunishLevel().value());// 20
		_buf.writeLong(player.getPunish().getPunishTimer());// 21
		_buf.flip();

		long totalOnlineTime = player.getOnlineTime();
		if (player.getOnlineBeginTime() > 0)
			totalOnlineTime += (System.currentTimeMillis() - player.getOnlineBeginTime()) / 1000;
		ConnectionProxy con = null;
		PreparedStatementProxy state = null;
		Object[] params;
		SqlData data = null;
		try {
			if (DBConnetionStateManager.getDbState()) {
				con = ConnectionProxy.newInstance();
				if (con != null)
					state = con.prepareStatement(UPDATE_CHARACTER);
				if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, state)) {
					params = new Object[] { System.currentTimeMillis(), player.getLevel(), player.getName(), player.getScene().get_id(), _buf, totalOnlineTime, player.isOnline(), player.getAppearance().getAnimationID(), player.getAppearance().getPaperDoll(), player.getFriendInstance().getIsLoginTip(), player.getFriendInstance().getProvince(), player.getFriendInstance().getCity(), player.getChatSwitches(), player.getAccessLevel().getLevel(), player.getObjectId() };
					data = new SqlData(SqlDataIdFactory.createSqlId("characters", player.getObjectId()), UPDATE_CHARACTER, params);
					DBConnetionStateManager.addDbTask(data);
					return true;
				} else {
					state.setLong(1, System.currentTimeMillis());
					state.setInt(2, player.getLevel());
					state.setString(3, player.getName());
					state.setInt(4, player.getScene().get_id());
					state.setBinaryStream(5, _buf, _buf.limit());
					state.setLong(6, totalOnlineTime);
					state.setInt(7, player.isOnline());
					state.setInt(8, player.getAppearance().getAnimationID());
					state.setInt(9, player.getAppearance().getPaperDoll());
					state.setInt(10, player.getFriendInstance().getIsLoginTip());
					state.setInt(11, player.getFriendInstance().getProvince());
					state.setInt(12, player.getFriendInstance().getCity());
					state.setShort(13, player.getChatSwitches());
					state.setInt(14, player.getAccessLevel().getLevel());
					state.setLong(15, player.getObjectId());
					int rs = state.executeUpdate();
					// �����ִ��ʱ�ɹ��������HeapByteBuffer
					if (rs != PreparedStatementProxy.NETWORKDISCONNECTION) {
						HeapByteBuffer.recycle(_buf);
						return true;
					} else {
						params = new Object[] { System.currentTimeMillis(), player.getLevel(), player.getName(), player.getScene().get_id(), _buf, totalOnlineTime, player.isOnline(), player.getAppearance().getAnimationID(), player.getAppearance().getPaperDoll(), player.getFriendInstance().getIsLoginTip(), player.getFriendInstance().getProvince(), player.getFriendInstance().getCity(), player.getChatSwitches(), player.getAccessLevel().getLevel(), player.getObjectId() };
						data = new SqlData(SqlDataIdFactory.createSqlId("characters", player.getObjectId()), UPDATE_CHARACTER, params);
						DBConnetionStateManager.addDbTask(data);
						return true;
					}
				}
			} else {
				params = new Object[] { System.currentTimeMillis(), player.getLevel(), player.getName(), player.getScene().get_id(), _buf, totalOnlineTime, player.isOnline(), player.getAppearance().getAnimationID(), player.getAppearance().getPaperDoll(), player.getFriendInstance().getIsLoginTip(), player.getFriendInstance().getProvince(), player.getFriendInstance().getCity(), player.getChatSwitches(), player.getAccessLevel().getLevel(), player.getObjectId() };
				data = new SqlData(SqlDataIdFactory.createSqlId("characters", player.getObjectId()), UPDATE_CHARACTER, params);
				DBConnetionStateManager.addDbTask(data);
				return true;

			}
		} finally {
			if (state != null)
				state.close();
			if (con != null)
				con.close();

		}
	}

	/**
	 * ����ָ����ɫ
	 * 
	 * @param id ��ɫID
	 * @return ��ɫ
	 */
	public static FuzePcInstance restoreplayer(long id) {
		ConnectionProxy con = null;
		FuzePcInstance player = null;
		PreparedStatementProxy state = null;
		ResultSet rset = null;
		HeapByteBuffer buf = HeapByteBuffer.newInstance();
		try {
			if (!DBConnetionStateManager.getDbState())
				return null;
			con = ConnectionProxy.newInstance();
			if (con != null)
				state = con.prepareStatement(LOAD_CHARACTER);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, state))
				return null;
			state.setLong(1, id);
			rset = state.executeQuery();
			if (rset == null)
				return null;
			int _practiceId;
			while (rset.next()) {
				String account_name = rset.getString(1);
				int sex = rset.getInt(3);
				int classid = rset.getInt(4);
				player = new FuzePcInstance(id, PlayerTemplateTable.getInstance().getTemplate(classid + sex), account_name, new PcAppearance(sex));
				player.setName(rset.getString(2));
				player.getStat().setLevel((byte) rset.getInt(5));
				player.getPosition().setScene(FuzeWorld.getInstance().getScene(rset.getInt(6)));
				// rset.getBytes(7);
				player.setOnlineTime(rset.getLong(8));
				// rset.getString(9);
				buf.clear();
				byte[] bytes = rset.getBytes(10);
				buf.write(bytes, 0, bytes.length);
				buf.flip();
				player.setCurrentHpTem(buf.readInt());
				player.setCurrentMpTem(buf.readInt());
				player.setExp(buf.readInt());
				player.setKarma(buf.readShort());
				long clanid = buf.readLong();
				if (clanid > 0) {
					player.setClan(ClanTable.getInstance().getClan(clanid));
				}
				_practiceId = buf.readByte();
				player.setPracticeId(_practiceId);
				player.getPosition().setScenePosition(buf.readShort(), buf.readShort());
				player.setAssignedSTR(buf.readInt());
				player.setAssignedDEX(buf.readInt());
				player.setAssignedINT(buf.readInt());
				player.setAssignedMEN(buf.readInt());
				player.setAssignedCON(buf.readInt());
				player.getStat().setUnassignedPoint(buf.readInt());
				int size = buf.readByte();
				int slotId;
				int shortcutType;
				long shortcutId;
				for (int i = 0; i < size; i++) {
					slotId = buf.readByte();
					shortcutType = buf.readByte();
					shortcutId = buf.readLong();
					player.registerShortCut(new L2ShortCut(slotId, shortcutType, shortcutId));
				}
				player.getStat().setAutoAddLevel(buf.readInt() != 0);
				int punish_level = 0;
				if (buf.remaining() >= 4) {
					punish_level = buf.readInt();
				}
				long punish_timer = 0;
				if (buf.remaining() >= 8) {
					punish_timer = buf.readLong();
				}
				player.setPunishLevel(punish_level, punish_timer);// ����ͷ��ȼ���ʱ��
				player.getAppearance().setAnimationID(rset.getInt(11));
				player.getAppearance().setPaperDoll(rset.getInt(12));
				player.getFriendInstance().setIsLoginTip(rset.getInt(13));// ������ʾ
				player.getFriendInstance().setProvince(rset.getInt(14));// ʡ
				player.getFriendInstance().setCity(rset.getInt(15));// ��
				player.setChatSwitches(rset.getShort(16));
				player.setAccessLevel(rset.getInt("accesslevel"));
			}

		} catch (Exception e) {
			_log.error("Error PlayerDb restoreplayer", Config.SERVER_ID, e);
			e.printStackTrace();
			player = null;
		} finally {
			HeapByteBuffer.recycle(buf);
			try {
				if (rset != null)
					rset.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (state != null)
				state.close();
			if (con != null)
				con.close();
		}
		return player;
	}

	/**
	 * ��ѯ�˻��µ����н�ɫ
	 * 
	 * @param accountname �˻����
	 * @return �˻��µ����н�ɫ
	 */
	public static List<CharSelectInfoPackage> selectCharinfo(String accountname) {
		CharSelectInfoPackage charInfopackage;
		List<CharSelectInfoPackage> characterList = new FastList<CharSelectInfoPackage>();
		ConnectionProxy con = null;
		PreparedStatementProxy state = null;
		ResultSet rs = null;
		try {
			if (!DBConnetionStateManager.getDbState())
				return characterList;
			con = ConnectionProxy.newInstance();
			if (con != null)
				state = con.prepareStatement(SELECT_ACCOUNT_CHARACTERS);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, state))
				return characterList;
			state.setString(1, accountname);
			rs = state.executeQuery();
			if (rs == null)
				return characterList;
			while (rs.next())// fills the package
			{
				charInfopackage = restoreChar(rs);
				if (charInfopackage != null)
					characterList.add(charInfopackage);
			}
			return characterList;
		} catch (Exception e) {
			_log.error("Error PlayerDb selectCharinfo", Config.SERVER_ID, e);
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (state != null)
				state.close();
			if (con != null)
				con.close();
		}

		return characterList;
	}

	private static CharSelectInfoPackage restoreChar(ResultSet chardata) throws Exception {
		long objectId = chardata.getLong("charId");
		String name = chardata.getString("char_name");
		// See if the char must be deleted
		long deletetime = chardata.getLong("deletetime");
		CharSelectInfoPackage charInfopackage = new CharSelectInfoPackage(objectId, name);
		charInfopackage.setLevel(chardata.getInt("level"));
		charInfopackage.setRace(ClassId.getClassId(chardata.getInt("classid")).getRace().getId());
		charInfopackage.setSceneId(chardata.getInt("scene"));
		charInfopackage.setDeleteTimer(deletetime);
		charInfopackage.setAppearance(chardata.getInt("appearance"));
		charInfopackage.setPaperdoll(chardata.getInt("paperdoll"));
		charInfopackage.setClanId(chardata.getInt("clanid"));
		return charInfopackage;
	}

	public static class UpdateOnlineStatus implements Runnable {
		private FuzePcInstance _activeChar;

		public UpdateOnlineStatus(FuzePcInstance activeChar) {
			super();
			_activeChar = activeChar;
		}

		@Override
		public void run() {
			// String sql =
			// "UPDATE characters SET online=?, lastAccess=? WHERE charId=?";
			ConnectionProxy con = null;
			PreparedStatementProxy ptmt = null;
			Object[] params = null;
			SqlData data = null;
			try {
				if (!DBConnetionStateManager.getDbState()) {
					params = new Object[] { _activeChar.isOnline(), System.currentTimeMillis(), _activeChar.getObjectId() };
					data = new SqlData(SqlDataIdFactory.createSqlId("characters_up_onlineStatus", _activeChar.getObjectId()), UPDATE_ONLINE_STATUS, params);
					DBConnetionStateManager.addDbTask(data);
				} else {

					con = ConnectionProxy.newInstance();
					if (con != null)
						ptmt = con.prepareStatement(UPDATE_ONLINE_STATUS);
					if (DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt)) {
						ptmt.setInt(1, _activeChar.isOnline());
						ptmt.setLong(2, System.currentTimeMillis());
						ptmt.setLong(3, _activeChar.getObjectId());
						int rs = ptmt.executeUpdate();
						if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
							params = new Object[] { _activeChar.isOnline(), System.currentTimeMillis(), _activeChar.getObjectId() };
							data = new SqlData(SqlDataIdFactory.createSqlId("characters_up_onlineStatus", _activeChar.getObjectId()), UPDATE_ONLINE_STATUS, params);
							DBConnetionStateManager.addDbTask(data);
						}
					} else {
						params = new Object[] { _activeChar.isOnline(), System.currentTimeMillis(), _activeChar.getObjectId() };
						data = new SqlData(SqlDataIdFactory.createSqlId("characters_up_onlineStatus", _activeChar.getObjectId()), UPDATE_ONLINE_STATUS, params);
						DBConnetionStateManager.addDbTask(data);
					}
				}

			} catch (SQLException e) {
				_log.error("character up onlineStatus", Config.SERVER_ID, e);
				e.printStackTrace();
			} finally {

				if (ptmt != null)
					ptmt.close();
				if (con != null)
					con.close();
			}

		}

	}

	public static void updateCharacterDeletetime(long charid, long deletetime) {
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		Object[] params = null;
		SqlData data = null;
		try {
			if (!DBConnetionStateManager.getDbState()) {
				params = new Object[] { deletetime, charid };
				data = new SqlData(SqlDataIdFactory.createSqlId("characters_up_deletetime", charid), UPDATE_CHARACTER_DELETE_TIME, params);
				DBConnetionStateManager.addDbTask(data);
			} else {
				con = ConnectionProxy.newInstance();
				if (con != null)
					ptmt = con.prepareStatement(UPDATE_CHARACTER_DELETE_TIME);
				if (DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt)) {
					ptmt.setLong(1, deletetime);
					ptmt.setLong(2, charid);
					int rs = ptmt.executeUpdate();
					if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
						params = new Object[] { deletetime, charid, };
						data = new SqlData(SqlDataIdFactory.createSqlId("characters_up_deletetime", charid), UPDATE_CHARACTER_DELETE_TIME, params);
						DBConnetionStateManager.addDbTask(data);
					}
				} else {
					params = new Object[] { deletetime, charid, };
					data = new SqlData(SqlDataIdFactory.createSqlId("characters_up_deletetime", charid), UPDATE_CHARACTER_DELETE_TIME, params);
					DBConnetionStateManager.addDbTask(data);
				}

			}

		} catch (SQLException e) {
			_log.error("character up delete time error", Config.SERVER_ID, e);
			e.printStackTrace();
		} finally {
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();

		}
	}

	/**
	 * ���ý�ɫ����Ƿ�ռ��
	 * 
	 * @param name ��ɫ���
	 * @return ����true ��������false;
	 */
	public static boolean doesCharNameExist(String name) {
		// String sql = "SELECT account_name FROM characters WHERE char_name=?";
		boolean result = true;
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rs = null;
		try {
			if (!DBConnetionStateManager.getDbState())
				return true;
			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(CHECK_CHARACTER_NAME_EXSIST);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
				return true;
			ptmt.setString(1, name);
			rs = ptmt.executeQuery();
			result = rs.next();
		} catch (Exception e) {
			_log.error("Error PlayerDb could not check existing charname:", Config.SERVER_ID, e);
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}
		return result;
	}

	/***
	 * �����˻������Ľ�ɫ����
	 * 
	 * @param account �˻����
	 * @return ���˻��µĽ�ɫ����
	 */
	public static int accountCharNumber(String account) {
		// String sql =
		// "SELECT COUNT(char_name) FROM characters WHERE account_name=?";
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rs = null;
		int number = 0;
		try {
			if (!DBConnetionStateManager.getDbState())
				return number;

			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(SELECT_ACCOUNT_CHARACTERS_COUNT);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
				return number;
			ptmt.setString(1, account);
			rs = ptmt.executeQuery();
			if (rs == null)
				return number;
			while (rs.next()) {
				number = rs.getInt(1);
			}
		} catch (Exception e) {
			_log.error("Error PlayerDb could not check existing char number:", Config.SERVER_ID, e);
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}

		return number;
	}

	/**
	 * ��ȡ���н�ɫ,��Map{String, Long} _chars������
	 * 
	 * @param _chars
	 */
	public static void loadAllcharacter(Map<String, Long> _chars) {
		String name;
		long id = -1;
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rs = null;
		try {
			if (!DBConnetionStateManager.getDbState())
				return;
			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(LOADALLCHARACTERS);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
				return;
			rs = ptmt.executeQuery();
			if (rs == null)
				return;
			while (rs.next()) {
				id = rs.getLong(1);
				name = rs.getString(2);
				_chars.put(name, id);
			}
		} catch (Exception e) {
			_log.error("Error PlayerDb could not load char name: ", Config.SERVER_ID, e);
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}
	}

	/**
	 * ��ݽ�ɫ��ƻ�ȡ��ɫID
	 * 
	 * @param name ��ɫ���
	 * @return ��ɫID
	 */
	public static long getIdByName(String name) {
		long id = -1;
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rs = null;
		try {
			if (!DBConnetionStateManager.getDbState())
				return id;
			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(SELECT_CHARACTERID_BY_NAME);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
				return id;
			ptmt.setString(1, name);
			rs = ptmt.executeQuery();
			if (rs == null)
				return id;
			while (rs.next()) {
				id = rs.getLong(1);
			}
		} catch (Exception e) {
			_log.error("Error PlayerDb could not check existing char name:", Config.SERVER_ID, e);
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}
		return id;
	}

	/**
	 * ��ݽ�ɫID���ҽ�ɫ���
	 * 
	 * @param ��ɫID
	 * @return ��ɫ���
	 */
	public static String getNameById(long id) {

		String name = null;
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rs = null;
		try {
			if (!DBConnetionStateManager.getDbState())
				return name;
			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(SELECT_CHARACTERNAME_BY_ID);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
				return name;
			ptmt.setLong(1, id);
			rs = ptmt.executeQuery();
			while (rs.next()) {
				name = rs.getString(1);
			}
		} catch (SQLException e) {
			_log.error("Error PlayerDb could not check existing char id:", Config.SERVER_ID, e);
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}
		return name;
	}

	/**
	 * ��ݽ�ɫID��ѯ����ID
	 * 
	 * @param charid ��ɫID
	 * @return ����ID
	 */
	public static long markToDeleteCharSelect(long charid) {

		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rs = null;
		long clanId = 0;
		try {
			if (!DBConnetionStateManager.getDbState())
				return clanId;
			con = ConnectionProxy.newInstance();
			if (con != null)
				ptmt = con.prepareStatement(SELECT_CLANID_BY_CHARACTERID);
			if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
				return clanId;
			ptmt.setLong(1, charid);
			rs = ptmt.executeQuery();
			if (rs == null)
				return clanId;
			while (rs.next()) {
				clanId = rs.getLong(1);
			}
		} catch (Exception e) {
			_log.error("Error PlayerDb markToDeleteChar", Config.SERVER_ID, e);
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}
		return clanId;
	}

	static public class CharSelectInfoPackage {

		private long _objectId;

		private String _name;

		private int _race;

		private long _deleteTimer;

		private long _lastAccess;

		private int _level = 1;

		private int sceneId;

		private int appearance;

		private int _paperdoll;

		private long _clanId;

		/**
		 * @param int1
		 */
		public CharSelectInfoPackage(long objectId, String name) {
			setObjectId(objectId);
			_name = name;
			// _paperdoll = PcInventory.restoreVisibleInventory(objectId);
		}

		public void setObjectId(long id) {
			_objectId = id;
		}

		public long getObjectId() {
			return _objectId;
		}

		public long getDeleteTimer() {
			return _deleteTimer;
		}

		public void setDeleteTimer(long deleteTimer) {
			_deleteTimer = deleteTimer;
		}

		public long getLastAccess() {
			return _lastAccess;
		}

		public void setLastAccess(long lastAccess) {
			_lastAccess = lastAccess;
		}

		// public int getPaperdollObjectId(int slot) {
		// return _paperdoll[slot][0];
		// }
		//
		// public int getPaperdollItemId(int slot) {
		// return _paperdoll[slot][1];
		// }

		public int getLevel() {
			return _level;
		}

		public int getPaperdoll() {
			return _paperdoll;
		}

		public void setPaperdoll(int paperdoll) {
			_paperdoll = paperdoll;
		}

		public void setLevel(int level) {
			_level = level;
		}

		public String getName() {
			return _name;
		}

		public void setName(String name) {
			_name = name;
		}

		public int getRace() {
			return _race;
		}

		public void setRace(int race) {
			_race = race;
		}

		public void setSceneId(int Id) {
			sceneId = Id;
		}

		public int getSceneId() {
			return sceneId;
		}

		public int getAppearance() {
			return appearance;
		}

		public void setAppearance(int appearance) {
			this.appearance = appearance;
		}

		public void setClanId(long clanId) {
			_clanId = clanId;
		}

		public long getClanId() {
			return _clanId;
		}

	}

	/**
	 * ��ݽ�ɫIDɾ����ݿ��¼
	 * 
	 * @param charId
	 */
	public static final void deleteCharByObjId(final long charId) {

		long objid = charId;
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		Object[] params = null;
		SqlData data = null;
		if (!DBConnetionStateManager.getDbState()) {

			params = new Object[] { objid };

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CHAR_BY_ID", objid), PHYSICAL_DELETE_CHAR_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_COMBATSET_BY_ID", objid), CombatSetDAO.PHYSICAL_DELETE_COMBATSET_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CONSIGNMENT_BY_ID", objid), ConsignmentDb.PHYSICAL_DELETE_CONSIGNMENT_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_ITEMS_BY_OWNERID", objid), ItemsDb.PHYSICAL_DELETE_ITEMS_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_QUESTS_BY_OWNERID", objid), PlayerQuest.PHYSICAL_DELETE_QUESTS_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_SKILL_BY_OWNERID", objid), PlayerSkills.PHYSICAL_DELETE_SKILL_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID", objid), PlayerSkills.PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID", objid), PlayFriends.PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

		}
		con = ConnectionProxy.newInstance();
		int rs;
		if (con != null) {
			try {
				con.setAutoCommit(false);
				// ɾ���ɫ
				ptmt = con.prepareStatement(PHYSICAL_DELETE_CHAR_BY_ID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CHAR_BY_ID", objid), PHYSICAL_DELETE_CHAR_BY_ID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				// ɾ���Զ�ս������
				ptmt = con.prepareStatement(CombatSetDAO.PHYSICAL_DELETE_COMBATSET_BY_ID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_COMBATSET_BY_ID", objid), CombatSetDAO.PHYSICAL_DELETE_COMBATSET_BY_ID, params);
					DBConnetionStateManager.addDbTask(data);
				}

				// ɾ�������Ʒ
				ptmt = con.prepareStatement(ConsignmentDb.PHYSICAL_DELETE_CONSIGNMENT_BY_ID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CONSIGNMENT_BY_ID", objid), ConsignmentDb.PHYSICAL_DELETE_CONSIGNMENT_BY_ID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				// ɾ�����Ʒ
				ptmt = con.prepareStatement(ItemsDb.PHYSICAL_DELETE_ITEMS_BY_OWNERID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_ITEMS_BY_OWNERID", objid), ItemsDb.PHYSICAL_DELETE_ITEMS_BY_OWNERID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				// ɾ������
				ptmt = con.prepareStatement(PlayerQuest.PHYSICAL_DELETE_QUESTS_BY_OWNERID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_QUESTS_BY_OWNERID", objid), PlayerQuest.PHYSICAL_DELETE_QUESTS_BY_OWNERID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				// ɾ����
				ptmt = con.prepareStatement(PlayerSkills.PHYSICAL_DELETE_SKILL_BY_OWNERID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_SKILL_BY_OWNERID", objid), PlayerSkills.PHYSICAL_DELETE_SKILL_BY_OWNERID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				// ɾ��Ч��
				ptmt = con.prepareStatement(PlayerSkills.PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID", objid), PlayerSkills.PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				// ɾ�����
				ptmt = con.prepareStatement(PlayFriends.PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID);
				ptmt.setLong(1, objid);
				rs = ptmt.executeUpdate();
				if (rs == PreparedStatementProxy.NETWORKDISCONNECTION) {
					params = new Object[] { objid };
					data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID", objid), PlayFriends.PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID, params);
					DBConnetionStateManager.addDbTask(data);
				}
				con.commit();
			} catch (SQLException e) {
				_log.error("ɾ���ɫʧ��  player=" + objid, Config.SERVER_ID, e);
				con.rollback();
			} finally {
				ptmt.close();
				con.close();
			}
		} else {

			params = new Object[] { objid };

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CHAR_BY_ID", objid), PHYSICAL_DELETE_CHAR_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_COMBATSET_BY_ID", objid), CombatSetDAO.PHYSICAL_DELETE_COMBATSET_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CONSIGNMENT_BY_ID", objid), ConsignmentDb.PHYSICAL_DELETE_CONSIGNMENT_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_ITEMS_BY_OWNERID", objid), ItemsDb.PHYSICAL_DELETE_ITEMS_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_QUESTS_BY_OWNERID", objid), PlayerQuest.PHYSICAL_DELETE_QUESTS_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_SKILL_BY_OWNERID", objid), PlayerSkills.PHYSICAL_DELETE_SKILL_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID", objid), PlayerSkills.PHYSICAL_DELETE_SKILLSAVE_BY_OWNERID, params);
			DBConnetionStateManager.addDbTask(data);

			data = new SqlData(SqlDataIdFactory.createSqlId("PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID", objid), PlayFriends.PHYSICAL_DELETE_CHARACTER_FRIENDS_BY_ID, params);
			DBConnetionStateManager.addDbTask(data);

		}

	}
}
